package com.example.mq.mqserver.core;

import java.io.Serializable;
import java.util.Arrays;
import java.util.UUID;

/*
* 表示要传递的消息
* 注意，此处的Message 对象，是需要在网络上传输，并且也需要能写入文件中
* 此时就需要针对Message 对象进行序列化和反序列化
* 此处使用 标准库自带的序列化和反序列化，不适用json,json本质是文本格式
* 里面放的是文本类型数据。而Message对象是二进制格式
* */
public class Message implements Serializable {
    // 序列化版本号，用于反序列化时判断版本是否一致
    private static final long serialVersionUID = 1L;

    // 通过BasicProperties来表示消息的属性
    private BasicProperties basicProperties = new BasicProperties();
    private byte[] body;

    // 下面属性是辅助属性
    // Message 后续会存储到文件中（如果持久化的话）
    // 使用文件而不使用数据库的原因是：
    // 1. 我们的消息并不需要强大的增删改查功能
    // 2. 消息太多，频繁的进行增删改查会导致性能问题

    // 一个文件存储很多消息的做法，如何找到某个消息呢？
    // 可以下列的偏移量来找到某个消息，[offsetBeg, offsetEnd)
    // 这两个不需要被序列化保存到文件中，此时消息一旦被写入文件后，所在的位置就固定了，并不需要单独存储
    // 这两个属性存在的目的，主要就算为了让内存中的Massage对象能够快速找到对应硬盘上的Message的位置
    private transient long offsetBeg = 0; // 消息数据的开头距离文件开头的偏移量（字节）
    private transient long offsetEnd = 0; // 消息数据的结尾距离文件开头的偏移量（字节）
    // 表示消息在文件中是否有效（逻辑删除：不是真的删除，而是被标记为无效）
    // 针对文件的删除，我们可以使用逻辑删除，0x1表示有效，0x0表示无效

    // isValid不是为了在内存中使用，而是为了在文件中使用，文件上最好是用字节表示
    private byte isValid = 0x1;

    // 创建一个工厂方法，用于创建一个Message对象
    // 创建的Message对象，会自动生成唯一的MessageId
    // 万一routingKey 和 basicProperties 里的routingKey 不一致，那么以basicProperties外面的为准
    public static Message createMessageWithId(String routingKey, BasicProperties basicProperties,byte[] body) {
        Message message = new Message();
        if(basicProperties != null) {
            message.setBasicProperties(basicProperties);
        }
        // 此处生成的MessageId 以M-开头
        message.setMessageId("M-"+UUID.randomUUID());
        message.basicProperties.setRoutingKey(routingKey);
        message.body = body;
        // 此处把body和basicProperties 先设置出来，它们是核心内容
        // 而 offsetBeg 和 offsetEnd 则是消息持久化才会用到，在把消息写入文件之前在进行设定
        // 此处只是在内存中创建Message对象
        return message;
    }

    // 为了快速拿到消息的id
    public String getMessageId() {
        return basicProperties.getMessageId();
    }

    public void setMessageId(String messageId) {
        basicProperties.setMessageId(messageId);
    }

    public String getRoutingKey() {
        return basicProperties.getRoutingKey();
    }

    public void setRoutingKey(String routingKey) {
        basicProperties.setRoutingKey(routingKey);
    }

    // 是否持久化
    public int getDeliveryMode() {
        return basicProperties.getDeliveryMode();
    }
    public void setDeliveryMode(int mode) {
        basicProperties.setDeliveryMode(mode);
    }

    public BasicProperties getBasicProperties() {
        return basicProperties;
    }

    public void setBasicProperties(BasicProperties basicProperties) {
        this.basicProperties = basicProperties;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    public long getOffsetBeg() {
        return offsetBeg;
    }

    public void setOffsetBeg(long offsetBeg) {
        this.offsetBeg = offsetBeg;
    }

    public long getOffsetEnd() {
        return offsetEnd;
    }

    public void setOffsetEnd(long offsetEnd) {
        this.offsetEnd = offsetEnd;
    }

    public byte getIsValid() {
        return isValid;
    }

    public void setIsValid(byte isValid) {
        this.isValid = isValid;
    }

    @Override
    public String toString() {
        return "Message{" +
                "basicProperties=" + basicProperties +
                ", body=" + Arrays.toString(body) +
                ", offsetBeg=" + offsetBeg +
                ", offsetEnd=" + offsetEnd +
                ", isValid=" + isValid +
                '}';
    }
}
